/*!
 * jQuery twitter bootstrap wizard plugin
 * Examples and documentation at: http://github.com/VinceG/twitter-bootstrap-wizard
 * version 1.3.1
 * Requires jQuery v1.3.2 or later
 * Supports Bootstrap 2.2.x, 2.3.x, 3.0
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 * Authors: Vadim Vincent Gabriel (http://vadimg.com), Jason Gill (www.gilluminate.com)
 */
;
(function($) {
    var bootstrapWizardCreate = function(element, options) {
        var element = $(element);
        var obj = this;

        // selector skips any 'li' elements that do not contain a child with a tab data-toggle
        var baseItemSelector = 'li:has([data-toggle="tab"])';
        var historyStack = [];

        // Merge options with defaults
        var $settings = $.extend({}, $.fn.bootstrapWizard.defaults, options);
        var $activeTab = null;
        var $navigation = null;

        this.rebindClick = function(selector, fn) {
            selector.unbind("click", fn).bind("click", fn);
        };

        this.fixNavigationButtons = function() {
            // Get the current active tab
            if (!$activeTab.length) {
                // Select first one
                $navigation.find("a:first").tab("show");
                $activeTab = $navigation.find(baseItemSelector + ":first");
            }

            // See if we're currently in the first/last then disable the previous and last buttons
            $($settings.previousSelector, element).toggleClass("disabled", (obj.firstIndex() >= obj.currentIndex()));
            $($settings.nextSelector, element).toggleClass("disabled", (obj.currentIndex() >= obj.navigationLength()));
            $($settings.nextSelector, element).toggleClass("hidden",
                (obj.currentIndex() >= obj.navigationLength() && $($settings.finishSelector, element).length > 0));
            $($settings.lastSelector, element).toggleClass("hidden",
                (obj.currentIndex() >= obj.navigationLength() && $($settings.finishSelector, element).length > 0));
            $($settings.finishSelector, element).toggleClass("hidden", (obj.currentIndex() < obj.navigationLength()));
            $($settings.backSelector, element).toggleClass("disabled", (historyStack.length == 0));
            $($settings.backSelector, element).toggleClass("hidden",
                (obj.currentIndex() >= obj.navigationLength() && $($settings.finishSelector, element).length > 0));

            // We are unbinding and rebinding to ensure single firing and no double-click errors
            obj.rebindClick($($settings.nextSelector, element), obj.next);
            obj.rebindClick($($settings.previousSelector, element), obj.previous);
            obj.rebindClick($($settings.lastSelector, element), obj.last);
            obj.rebindClick($($settings.firstSelector, element), obj.first);
            obj.rebindClick($($settings.finishSelector, element), obj.finish);
            obj.rebindClick($($settings.backSelector, element), obj.back);

            if ($settings.onTabShow &&
                typeof $settings.onTabShow === "function" &&
                $settings.onTabShow($activeTab, $navigation, obj.currentIndex()) === false) {
                return false;
            }
        };

        this.next = function(e) {
            // If we clicked the last then dont activate this
            if (element.hasClass("last")) {
                return false;
            }

            if ($settings.onNext &&
                typeof $settings.onNext === "function" &&
                $settings.onNext($activeTab, $navigation, obj.nextIndex()) === false) {
                return false;
            }

            var formerIndex = obj.currentIndex();
            var $index = obj.nextIndex();

            // Did we click the last button
            if ($index > obj.navigationLength()) {
            } else {
                historyStack.push(formerIndex);
                $navigation.find(baseItemSelector + ($settings.withVisible ? ":visible" : "") + ":eq(" + $index + ") a")
                    .tab("show");
            }
        };

        this.previous = function(e) {
            // If we clicked the first then dont activate this
            if (element.hasClass("first")) {
                return false;
            }

            if ($settings.onPrevious &&
                typeof $settings.onPrevious === "function" &&
                $settings.onPrevious($activeTab, $navigation, obj.previousIndex()) === false) {
                return false;
            }

            var formerIndex = obj.currentIndex();
            var $index = obj.previousIndex();

            if ($index < 0) {
            } else {
                historyStack.push(formerIndex);
                $navigation.find(baseItemSelector + ($settings.withVisible ? ":visible" : "") + ":eq(" + $index + ") a")
                    .tab("show");
            }
        };

        this.first = function(e) {
            if ($settings.onFirst &&
                typeof $settings.onFirst === "function" &&
                $settings.onFirst($activeTab, $navigation, obj.firstIndex()) === false) {
                return false;
            }

            // If the element is disabled then we won't do anything
            if (element.hasClass("disabled")) {
                return false;
            }

            historyStack.push(obj.currentIndex());
            $navigation.find(baseItemSelector + ":eq(0) a").tab("show");
        };

        this.last = function(e) {
            if ($settings.onLast &&
                typeof $settings.onLast === "function" &&
                $settings.onLast($activeTab, $navigation, obj.lastIndex()) === false) {
                return false;
            }

            // If the element is disabled then we won't do anything
            if (element.hasClass("disabled")) {
                return false;
            }

            historyStack.push(obj.currentIndex());
            $navigation.find(baseItemSelector + ":eq(" + obj.navigationLength() + ") a").tab("show");
        };

        this.finish = function(e) {
            if ($settings.onFinish && typeof $settings.onFinish === "function") {
                $settings.onFinish($activeTab, $navigation, obj.lastIndex());
            }
        };

        this.back = function() {
            if (historyStack.length == 0) {
                return null;
            }

            var formerIndex = historyStack.pop();
            if ($settings.onBack &&
                typeof $settings.onBack === "function" &&
                $settings.onBack($activeTab, $navigation, formerIndex) === false) {
                historyStack.push(formerIndex);
                return false;
            }

            element.find(baseItemSelector + ":eq(" + formerIndex + ") a").tab("show");
        };

        this.currentIndex = function() {
            return $navigation.find(baseItemSelector).index($activeTab);
        };

        this.firstIndex = function() {
            return 0;
        };

        this.lastIndex = function() {
            return obj.navigationLength();
        };
        this.getIndex = function(e) {
            return $navigation.find(baseItemSelector).index(e);
        };
        this.nextIndex = function() {
            return $navigation.find(baseItemSelector).index($activeTab) + 1;
        };
        this.previousIndex = function() {
            return $navigation.find(baseItemSelector).index($activeTab) - 1;
        };
        this.navigationLength = function() {
            return $navigation.find(baseItemSelector).length - 1;
        };
        this.activeTab = function() {
            return $activeTab;
        };
        this.nextTab = function() {
            return $navigation.find(baseItemSelector + ":eq(" + (obj.currentIndex() + 1) + ")").length
                ? $navigation.find(baseItemSelector + ":eq(" + (obj.currentIndex() + 1) + ")")
                : null;
        };
        this.previousTab = function() {
            if (obj.currentIndex() <= 0) {
                return null;
            }
            return $navigation.find(baseItemSelector + ":eq(" + parseInt(obj.currentIndex() - 1) + ")");
        };
        this.show = function(index) {
            var tabToShow = isNaN(index)
                ? element.find(baseItemSelector + " a[href=#" + index + "]")
                : element.find(baseItemSelector + ":eq(" + index + ") a");
            if (tabToShow.length > 0) {
                historyStack.push(obj.currentIndex());
                tabToShow.tab("show");
            }
        };
        this.disable = function(index) {
            $navigation.find(baseItemSelector + ":eq(" + index + ")").addClass("disabled");
        };
        this.enable = function(index) {
            $navigation.find(baseItemSelector + ":eq(" + index + ")").removeClass("disabled");
        };
        this.hide = function(index) {
            $navigation.find(baseItemSelector + ":eq(" + index + ")").hide();
        };
        this.display = function(index) {
            $navigation.find(baseItemSelector + ":eq(" + index + ")").show();
        };
        this.remove = function(args) {
            var $index = args[0];
            var $removeTabPane = typeof args[1] != "undefined" ? args[1] : false;
            var $item = $navigation.find(baseItemSelector + ":eq(" + $index + ")");

            // Remove the tab pane first if needed
            if ($removeTabPane) {
                var $href = $item.find("a").attr("href");
                $($href).remove();
            }

            // Remove menu item
            $item.remove();
        };

        var innerTabClick = function(e) {
            // Get the index of the clicked tab
            var $ul = $navigation.find(baseItemSelector);
            var clickedIndex = $ul.index($(e.currentTarget).parent(baseItemSelector));
            var $clickedTab = $($ul[clickedIndex]);
            if ($settings.onTabClick &&
                typeof $settings.onTabClick === "function" &&
                $settings.onTabClick($activeTab, $navigation, obj.currentIndex(), clickedIndex, $clickedTab) ===
                false) {
                return false;
            }
        };

        var innerTabShown = function(e) { // use shown instead of show to help prevent double firing
            var $element = $(e.target).parent();
            var nextTab = $navigation.find(baseItemSelector).index($element);

            // If it's disabled then do not change
            if ($element.hasClass("disabled")) {
                return false;
            }

            if ($settings.onTabChange &&
                typeof $settings.onTabChange === "function" &&
                $settings.onTabChange($activeTab, $navigation, obj.currentIndex(), nextTab) === false) {
                return false;
            }

            $activeTab = $element; // activated tab
            obj.fixNavigationButtons();
        };

        this.resetWizard = function() {

            // remove the existing handlers
            $('a[data-toggle="tab"]', $navigation).off("click", innerTabClick);
            $('a[data-toggle="tab"]', $navigation).off("shown shown.bs.tab", innerTabShown);

            // reset elements based on current state of the DOM
            $navigation = element.find("ul:first", element);
            $activeTab = $navigation.find(baseItemSelector + ".active", element);

            // re-add handlers
            $('a[data-toggle="tab"]', $navigation).on("click", innerTabClick);
            $('a[data-toggle="tab"]', $navigation).on("shown shown.bs.tab", innerTabShown);

            obj.fixNavigationButtons();
        };

        $navigation = element.find("ul:first", element);
        $activeTab = $navigation.find(baseItemSelector + ".active", element);

        if (!$navigation.hasClass($settings.tabClass)) {
            $navigation.addClass($settings.tabClass);
        }

        // Load onInit
        if ($settings.onInit && typeof $settings.onInit === "function") {
            $settings.onInit($activeTab, $navigation, 0);
        }

        // Load onShow
        if ($settings.onShow && typeof $settings.onShow === "function") {
            $settings.onShow($activeTab, $navigation, obj.nextIndex());
        }

        $('a[data-toggle="tab"]', $navigation).on("click", innerTabClick);

        // attach to both shown and shown.bs.tab to support Bootstrap versions 2.3.2 and 3.0.0
        $('a[data-toggle="tab"]', $navigation).on("shown shown.bs.tab", innerTabShown);
    };
    $.fn.bootstrapWizard = function(options) {
        //expose methods
        if (typeof options == "string") {
            var args = Array.prototype.slice.call(arguments, 1);
            if (args.length === 1) {
                args.toString();
            }
            return this.data("bootstrapWizard")[options](args);
        }
        return this.each(function(index) {
            var element = $(this);
            // Return early if this element already has a plugin instance
            if (element.data("bootstrapWizard")) return;
            // pass options to plugin constructor
            var wizard = new bootstrapWizardCreate(element, options);
            // Store plugin object in this element's data
            element.data("bootstrapWizard", wizard);
            // and then trigger initial change
            wizard.fixNavigationButtons();
        });
    };

// expose options
    $.fn.bootstrapWizard.defaults = {
        withVisible: true,
        tabClass: "nav nav-pills",
        nextSelector: ".wizard li.next",
        previousSelector: ".wizard li.previous",
        firstSelector: ".wizard li.first",
        lastSelector: ".wizard li.last",
        finishSelector: ".wizard li.finish",
        backSelector: ".wizard li.back",
        onShow: null,
        onInit: null,
        onNext: null,
        onPrevious: null,
        onLast: null,
        onFirst: null,
        onFinish: null,
        onBack: null,
        onTabChange: null,
        onTabClick: null,
        onTabShow: null
    };

})(jQuery);
